package top.xia17.plugins.fast.auth.rest;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import top.xia17.plugins.fast.common.model.Back;
import top.xia17.plugins.fast.common.exceptions.BadRequestException;
import top.xia17.plugins.fast.common.security.anonymous.AnonymousPostMapping;
import top.xia17.plugins.fast.common.utils.web.RequestUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.xia17.plugins.fast.auth.autoconfiguraion.AuthProperties;
import top.xia17.plugins.fast.auth.model.req.RegisterCodeSendReq;
import top.xia17.plugins.fast.auth.model.req.UserRegisterReq;
import top.xia17.plugins.fast.auth.register.RegisterCodeLauncher;
import top.xia17.plugins.fast.auth.register.RegisterCodeLauncherManager;
import top.xia17.plugins.fast.auth.register.RegisterProperties;
import top.xia17.plugins.fast.user.dao.entity.Dept;
import top.xia17.plugins.fast.user.dao.entity.Role;
import top.xia17.plugins.fast.user.dao.entity.User;
import top.xia17.plugins.fast.user.model.dto.UserDto;
import top.xia17.plugins.fast.user.service.UserService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 注册接口
 *
 * @author xia17
 * @date 2022/4/7
 */
@RestController
@RequestMapping("auth/register")
@RequiredArgsConstructor
@Slf4j
public class RegisterRest {

    private final RegisterCodeLauncherManager registerCodeLauncherManager;
    private final UserService userService;
    private final AuthProperties authProperties;


    /**
     * 用户注册
     * synchronized 加锁防止重复注册
     *
     * @param req 请求信息
     * @return /
     */
    @AnonymousPostMapping
    public synchronized Back<String> register(@RequestBody UserRegisterReq req) {
        // 注册接口是否开放
        if (!authProperties.getRegister().getOpen()) {
            throw new BadRequestException("注册接口已关闭！");
        }
        // 用户名重复判断
        if (userService.getByUsername(req.getUsername()).isPresent()) {
            throw new BadRequestException("用户名已存在！");
        }
        // 注册验证码
        RegisterCodeLauncher registerCodeLauncher = registerCodeLauncherManager.obtainSupport(req.getRegisterCodeLauncher());
        int codeVerify = registerCodeLauncher.verify(req.getRegisterCodeUuid(), registerCodeLauncher.getToByReq(req), req.getRegisterCode());
        if (codeVerify == -1) {
            throw new BadRequestException("验证码已失效！");
        } else if (codeVerify == 0) {
            throw new BadRequestException("验证码错误");
        }
        // 默认信息
        RegisterProperties.DefaultUserInfoProperties defaultUserInfo = authProperties.getRegister().getDefaultUserInfo();
        User user = new User()
                .setUsername(req.getUsername())
                .setPassword(req.getPassword())
                .setNickname(req.getNickname())
                .setEmail(req.getEmail())
                .setPhone(req.getPhone())
                .setRoles(new HashSet<>())
                .setEnabled(defaultUserInfo.getEnabled())
                .setIsFreeze(defaultUserInfo.getIsFreeze());
        // 附加值
        JSONObject defaultExtra = JSONUtil.parseObj(defaultUserInfo.getExtra());
        if (StrUtil.isNotBlank(req.getExtra())) {
            JSONObject jsonObject = JSONUtil.parseObj(req.getExtra());
            defaultExtra.putAll(jsonObject);
        }
        user.setExtra(defaultExtra.toString());
        // 默认部门
        if (defaultUserInfo.getDeptId() != null) {
            user.setDept(new Dept().setId(defaultUserInfo.getDeptId()));
        }
        // 默认角色
        if (defaultUserInfo.getRoleIds() != null) {
            Set<Role> roles = Arrays.stream(defaultUserInfo.getRoleIds())
                    .map(roleId -> new Role().setId(roleId))
                    .collect(Collectors.toSet());
            user.setRoles(roles);
        }
        // 密码生成器
        String passwordGenerator = authProperties.getRegister().getPasswordGenerator();
        UserDto userDto = userService.register(user, passwordGenerator);
        // 注册成功后删除验证码
        registerCodeLauncher.del(req.getRegisterCodeUuid());
        Back<String> res = Back.ok();
        if (!authProperties.getRegister().getInputPass()) {
            // 返回密码
            res.setExtra(userDto.getPassword());
        }
        return res;
    }


    /**
     * 发送注册验证码
     * 返回此次发送验证码的uuid
     * @param request 请求信息
     * @param req 参数
     * @return 返回此次发送验证码的uuid
     */
    @AnonymousPostMapping("send_code")
    public Back<String> sendCode(HttpServletRequest request , @RequestBody @Valid RegisterCodeSendReq req){
        RegisterCodeLauncher launcher = registerCodeLauncherManager.obtainSupport(req.getRegisterCodeLauncher());
        RegisterProperties registerProperties = authProperties.getRegister();
        if (!registerProperties.getSendCodeLimitEnabled()){
            // 无发送次数限制
            String uuid = launcher.send(req.getTo());
            return Back.okStr(uuid);
        }
        String tag ;
        String limitTagType = registerProperties.getSendCodeLimitTagType();
        switch (limitTagType){
            case "IP":
                tag = RequestUtil.getIp(request);
                break;
            case "TO":
                tag = req.getTo();
                break;
            default:{
                log.error("注册验证码发送次数限制标志类型配置异常,不支持的配置：{}",limitTagType);
                throw new BadRequestException("系统异常，后台配置异常");
            }
        }
        String uuid = launcher.send(tag,req.getTo());
        return Back.okStr(uuid);
    }


}
